#include "cEffectManager.h"

#include "..\util\logger.h"
#include "..\util\ut.h"

void cEffectManager::Initialize( ID3D10Device * _device )
{
	device = _device;
}

cEffectPtr cEffectManager::Load( std::wstring filename, std::vector<InputElement> ID )
{
	auto iter = EffectData.find(filename);

	if(iter != EffectData.end())
	{
		return cEffectPtr(iter->second);
	}
	else
	{
		cEffect * ptr = nullptr;
		ptr = new cEffect;
		if(!LoadShader(filename, ID, ptr))
		{
			MainLog.Error(true, L"Unable to compile " + filename + L", error");
			return cEffectPtr();
		}
		else
		{
			EffectData[filename] = ptr;
			return cEffectPtr(ptr);
		}
	}
}

bool cEffectManager::LoadShader( std::wstring filename, std::vector<InputElement> ID, cEffect * effect )
{
	if(ID.size() == 0)
	{
		delete effect;
		return false;
	}

	int shaderFlags = 0;
	ID3D10Blob* compilationErrors = nullptr;
	if(FAILED(D3DX10CreateEffectFromFile(filename.c_str(), NULL, NULL, "fx_4_0", shaderFlags, 
		NULL, device, NULL, NULL, &effect->Shader, &compilationErrors, NULL)))
	{
		delete effect;
		std::string temp = (char*)compilationErrors->GetBufferPointer();
		MainLog.Error(false, utils::StrToWStr(temp));
		return false;
	}
	effect->Tech = effect->Shader->GetTechniqueByIndex(0);
	effect->Pass = effect->Tech->GetPassByIndex(0);

	D3D10_INPUT_ELEMENT_DESC * ilDesc = new D3D10_INPUT_ELEMENT_DESC[ID.size()];
	int align = 0;

	for (unsigned int i = 0; i < ID.size() ; i++)
	{
		ilDesc[i].AlignedByteOffset = align;
		if(ID[i].ByteWidth == 1)
			ilDesc[i].Format = DXGI_FORMAT_R32_FLOAT;
		if(ID[i].ByteWidth == 2)
			ilDesc[i].Format = DXGI_FORMAT_R32G32_FLOAT;
		if(ID[i].ByteWidth == 3)
			ilDesc[i].Format = DXGI_FORMAT_R32G32B32_FLOAT;
		if(ID[i].ByteWidth == 4)
			ilDesc[i].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
		ilDesc[i].InputSlot = 0;
		ilDesc[i].InputSlotClass = D3D10_INPUT_PER_VERTEX_DATA;
		ilDesc[i].InstanceDataStepRate = 0;
		ilDesc[i].SemanticIndex = 0;
		ilDesc[i].SemanticName = ID[i].Name;
		align += ID[i].ByteWidth * 4;
	}

	D3D10_PASS_DESC passDesc;
	effect->Tech->GetPassByIndex(0)->GetDesc(&passDesc);
	if(FAILED(device->CreateInputLayout(ilDesc, ID.size(), passDesc.pIAInputSignature, passDesc.IAInputSignatureSize, &effect->IL)))
	{
		delete effect;
		MainLog.Error(true, L"Unable to create input layout for shader: " + filename);
		return false;
	}

	return true;
}